#include "xRenderObject.h"
#include "xSceneNode.h"
#include "xLine3D.h"






namespace XE
{


    xRenderObject::~xRenderObject()
	{
		if(m_pAttachNode!=NULL)
			m_pAttachNode->DetachRenderObject(this);

	}


	bool xRenderObject::DetachFormSceneNode()
	{
		if(m_pAttachNode==NULL)
			return false;

     return m_pAttachNode->DetachRenderObject(this);

	}

	const xMatrix* xRenderObject::GetWorldMatrix()
	{
		if(m_pAttachNode!=NULL)
			return  m_pAttachNode->GetWorldMatrix();
		if(m_pParentNode!=NULL&&m_pParentObje!=NULL)
		{

			static xMatrix mat;
			mat= (*m_pParentNode->GetWorldMatrix())*(* m_pParentObje->GetWorldMatrix());
			return &mat;
		}
		static xMatrix DeMat;
		xMath::MatrixIdentity(DeMat);
		return &DeMat;

	}

     HRESULT xRenderObject::Render(XRenderSystem* pRender,xCamera* pCamera)
	 {
		 return pRender->SetWorldMatrix(GetWorldMatrix());
	 }


	 HRESULT xRenderObject::PreRenderCallBack(XRenderSystem* pRender,xCamera* pCamera,xRenderEntry* pEntry,const u32Flags* RenderFlag)
	 {
		 pRender->SetWorldMatrix(GetWorldMatrix());
		 xRenderScheme* pTech =pEntry->m_pRenderScheme;

		 for(int i = 0;i<pTech->GetTexutreNumber();++i)
		 {
			 pRender->SetTexture(i,pTech->GetTexture(i).getPointer());
		 }
		 pRender->SetTexture(pTech->GetTexutreNumber(),NULL);


		  xShaderPtr pShader = pEntry->m_pRenderScheme->GetShader();
		  if(RenderFlag->testBit(Active_Technique)||RenderFlag->testBit(Active_Shader))
		  {

			
			 	F(pShader->Begin(0));
			  	F(pShader->BeginPass(pEntry->m_PassIndex));

		  }else if(RenderFlag->testBit(Active_Pass))
		  {
			 	F(pShader->BeginPass(pEntry->m_PassIndex));
		  }

		  if(pEntry->m_pRenderScheme->UpdateParameter(pRender)==false)
		  {
			  return X_FAIL;
		  }

		pShader->CommitChanges();




		  return X_OK;

	 }


     HRESULT xRenderObject::PostRenderCallBack(XRenderSystem* pRender,xCamera* pCamera,xRenderEntry* pEntry,const u32Flags*	 RenderFlag)
	 {

		 if(RenderFlag->testBit(Active_Pass))
		 {
			 xShaderPtr pShader = pEntry->m_pRenderScheme->GetShader();
			 pShader->EndPass();
		 }

		 if(RenderFlag->testBit(Active_Technique)||RenderFlag->testBit(Active_Shader))
		 {
			 xShaderPtr pShader = pEntry->m_pRenderScheme->GetShader();
			 pShader->EndPass();
			 pShader->End();
		 }

		 return X_OK;

	 }




	 void  xRenderObject::_updateRenderQueue(xRenderQueue* pRenderQueue,const xCamera* pCamera)
	 {
		 if(IsVisual())
		 {
			 pRenderQueue->AddRenderObject(this);
			// if(isRenderBox()&&m_pli)
		 }

		 return ;
	 }

	 void  xRenderObject::EnableRenderBox(bool b)
	 {
		 if(b==m_RenderBox)
			 return ;
		 m_RenderBox = b;
		 if(!b&&m_pBoxLine!=NULL)
		 {
          m_pSceneMrg->DestoryRenderObject(m_pBoxLine);
		  m_pBoxLine=NULL;
		 }else if(m_RenderBox)
		 {
			 if(m_pBoxLine)
			 {
				 m_pSceneMrg->DestoryRenderObject(m_pBoxLine);
				 m_pBoxLine=NULL;
			 }
			 m_pBoxLine=BuildBox();
			 if(m_pAttachNode)
			 {
				 m_pAttachNode->AttachRenderObject(m_pBoxLine);
			 }

		 }
	 }

	 xLine3d* xRenderObject::BuildBox()
	 {

		 const xBox* pBox =GetLocalBox();
		 if(pBox==NULL)
			 return NULL ;

		 xString name = GetName();
		 name+="_Box";
		 xLine3DCreateParameter line3dPara(name, 24,xColor(1.0f,1.0f,1.0f,1.0f));
		 xLine3d* pline3d = static_cast<xLine3d*>(m_pSceneMrg->CreateRenderObject(line3dPara));
		 if(pline3d==NULL)
			 return pline3d;
		
		 pline3d->Lock();
		 pline3d->SetPoint(0,pBox->GetCorner(0));
		 pline3d->SetPoint(1,pBox->GetCorner(1));

		 pline3d->SetPoint(2,pBox->GetCorner(1));
		 pline3d->SetPoint(3,pBox->GetCorner(2));

		 pline3d->SetPoint(4,pBox->GetCorner(2));
		 pline3d->SetPoint(5,pBox->GetCorner(3));

		 pline3d->SetPoint(6,pBox->GetCorner(3));
		 pline3d->SetPoint(7,pBox->GetCorner(0));
		 //------------------------------------------------------------
		 pline3d->SetPoint(8,pBox->GetCorner(4));
		 pline3d->SetPoint(9,pBox->GetCorner(5));

		 pline3d->SetPoint(10,pBox->GetCorner(5));
		 pline3d->SetPoint(11,pBox->GetCorner(6));

		 pline3d->SetPoint(12,pBox->GetCorner(6));
		 pline3d->SetPoint(13,pBox->GetCorner(7));

		 pline3d->SetPoint(14,pBox->GetCorner(7));
		 pline3d->SetPoint(15,pBox->GetCorner(4));
		 //--------------------------------------------------------

		 pline3d->SetPoint(16,pBox->GetCorner(1));
		 pline3d->SetPoint(17,pBox->GetCorner(5));

		 pline3d->SetPoint(18,pBox->GetCorner(2));
		 pline3d->SetPoint(19,pBox->GetCorner(4));

		 pline3d->SetPoint(20,pBox->GetCorner(3));
		 pline3d->SetPoint(21,pBox->GetCorner(7));

		 pline3d->SetPoint(22,pBox->GetCorner(0));
		 pline3d->SetPoint(23,pBox->GetCorner(6));
		 return pline3d;


	 }

	 void xRenderObject::NotifyAttach(xSceneNode* pnode)
	 {
		 m_pAttachNode = pnode;
		 if(m_pBoxLine!=NULL&&m_pAttachNode!=NULL)
		 {
			 pnode->AttachRenderObject(m_pBoxLine);
		 }

	 }


	 void xRenderObject::NotifyDeath(xSceneNode* pNode)
	 {
		 m_pAttachNode=NULL;
		 if(m_pBoxLine!=NULL&&pNode!=NULL)
		 {
			 pNode->DetachRenderObject(m_pBoxLine);
		 }
		 return ;

	 }
}